﻿using System;
using System.IO;
using System.Text;
using UtilZ.Dotnet.Ex.Base;
using UtilZ.Dotnet.Ex.Communication.Net.Base;
using UtilZ.Dotnet.Ex.Model;
using UtilZ.Dotnet.Ex.ZLog;

namespace UtilZ.Dotnet.Ex.Communication.Net.Ftp
{
    internal abstract class FtpDataTranferAbs : IDisposable
    {
        protected readonly FtpSession _session;
        private FtpTransferClient _ftpClient = null;

        /// <summary>
        /// 构造函数
        /// </summary>
        public FtpDataTranferAbs(FtpSession session)
        {
            this._session = session;
        }




        /// <summary>
        /// 发送数据
        /// </summary>
        /// <param name="bufferData">数据</param>
        public void SendData(DataSource bufferData)
        {
            switch (bufferData.DataType)
            {
                case DataSourceType.Bytes:
                    this._ftpClient.Send(bufferData.Bytes);
                    break;
                case DataSourceType.File:
                    this._ftpClient.SendFile(bufferData, this._session.DataTransferFormat);
                    break;
            }
        }






        /// <summary>
        /// 创建tcp连接-下载文件[连接成功返回true,失败返回false]
        /// </summary>
        /// <param name="response">ftp响应</param>
        /// <returns>连接成功返回true,失败返回false</returns>
        public bool CreateSendDataTcpClient(out IFtpResponse response)
        {
            return this.CreateTcpClient(null, false, out response);
        }

        /// <summary>
        /// 创建tcp连接-上传文件[连接成功返回true,失败返回false]
        /// </summary>
        /// <param name="filePath">接收数据文件路径,发送数据时参数为null</param>
        /// <param name="append">true:追加数据到已存在的文件,文件不存在则创建;false:总是创建新文件,如果旧文件存在则替换</param>
        /// <param name="response">ftp响应</param>
        /// <returns>连接成功返回true,失败返回false</returns>
        public bool CreateReceiveTcpClient(string filePath, bool append, out IFtpResponse response)
        {
            return this.CreateTcpClient(filePath, append, out response);
        }

        /// <summary>
        /// 创建tcp连接[连接成功返回true,失败返回false]
        /// </summary>
        /// <param name="filePath">接收数据文件路径,发送数据时参数为null</param>
        /// <param name="append">true:追加数据到已存在的文件,文件不存在则创建;false:总是创建新文件,如果旧文件存在则替换</param>
        /// <param name="response">ftp响应</param>
        /// <returns>连接成功返回true,失败返回false</returns>
        private bool CreateTcpClient(string filePath, bool append, out IFtpResponse response)
        {
            try
            {
                this._ftpClient = this.PrimitiveCreateTcpClient(filePath, append);
                string message;
                if (filePath == null)
                {
                    message = "Data connection already open; transfer starting.";
                }
                else
                {
                    string fileName = Path.GetFileName(filePath);
                    message = $"fileName:{fileName}.Data connection already open; transfer starting.";
                }

                response = new FtpCodeResponse(FtpStatusCodes.Code125, message);
                return true;
            }
            catch (Exception ex)
            {
                ZLoger.Warn(ex, $"建立数据连接失败");
                response = new FtpCodeResponse(FtpStatusCodes.Code425);
                return false;
            }
        }


        /// <summary>
        /// 创建tcp连接
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="append">true:追加数据到已存在的文件,文件不存在则创建;false:总是创建新文件,如果旧文件存在则替换</param>
        /// <returns>创建的tcp连接</returns>
        protected abstract FtpTransferClient PrimitiveCreateTcpClient(string filePath, bool append);








        /// <summary>
        /// 获取ftp响应
        /// </summary>
        /// <returns>ftp响应</returns>
        public IFtpResponse GetFtpResponse()
        {
            return this.PrimitiveGetFtpResponse();
        }

        /// <summary>
        /// 获取ftp响应
        /// </summary>
        /// <returns>ftp响应</returns>
        protected abstract IFtpResponse PrimitiveGetFtpResponse();




        /// <summary>
        /// 接收数据
        /// </summary>
        /// <returns></returns>
        public IFtpResponse ReceiveData()
        {
            //Response: 226 Transfer complete.
            this._ftpClient.ReceiveData();
            FtpCodeResponse res;
            var ex = this._ftpClient.ReceiveException;
            if (ex != null)
            {
                if (ex is IOException)
                {
                    res = new FtpCodeResponse(FtpStatusCodes.Code452);
                }
                else
                {
                    res = new FtpCodeResponse(FtpStatusCodes.Code451);
                }
            }
            else
            {
                res = new FtpCodeResponse(FtpStatusCodes.Code226, "Transfer complete.");
            }

            return res;
        }







        private bool _disposed = false;
        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            if (this._disposed)
            {
                return;
            }
            this._disposed = true;

            this.Dispose(true);

            if (this._ftpClient != null)
            {
                this._ftpClient.Dispose();
                this._ftpClient = null;
            }

            this._session.RemoveDataTranfer(this);
        }


        /// <summary>
        /// 释放资源
        /// </summary>
        /// <param name="disposing">disposing</param>
        protected virtual void Dispose(bool disposing)
        {

        }
    }
}
